#pragma once
#include <iostream>
#include <queue>
#include <pthread.h>
#include "Thread.hpp"
#include "LockGuard.hpp"
#include <mutex>
enum {gnum = 3};

template <class T>
class ThreadPool;

template <class T>
class ThreadPoolData
{
public:
    ThreadPoolData(ThreadPool<T> *tp, const std::string &threadName)
        : _tp(tp), _threadName(threadName)
    {
    }
    ThreadPool<T> *_tp;
    std::string _threadName;
};

template <class T>
class ThreadPool
{
    //垃圾回收栈GC
    class GC
    {
        ~GC()
        {
            delInstance();
        }
    };

private:
    ThreadPool(int num = gnum)
        : _threadNum(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        for (int i = 0; i < _threadNum; ++i)
        {
            _threads.push_back(new Thread());
        }
    }
    ThreadPool(const ThreadPool<T> &) = delete;
    ThreadPool<T> &operator=(const ThreadPool<T> &) = delete;
    static void *handlerTask(void *args)
    {
        ThreadPoolData<T> *tpd = static_cast<ThreadPoolData<T> *>(args);
        while (true)
        {
            T t;
            {
                LockGuard lg(tpd->_tp->GetMutex());
                while (tpd->_tp->isTaskQueueEmpty())
                {
                    tpd->_tp->ThreadWait();
                }
                // 此时任务队列不为空
                t = tpd->_tp->pop(); // 此时线程拿到任务，但是不能在锁内执行任务，不然会造成串行
            }
            std::cout << tpd->_threadName << " 获得了一个任务: " << t.ToString() << " 并处理完成，结果是: " << t() << std::endl;
        }

        delete tpd;
        return nullptr;
    }

    //获取任务
    T pop()
    {
        // 此时一定处于加锁状态，是线程安全的
        T t = _taskQueue.front();
        _taskQueue.pop();
        return t;
    }

    //判断临界资源是否为空
    bool isTaskQueueEmpty()
    {
        return _taskQueue.empty();
    }
    //获取互斥锁
    pthread_mutex_t &GetMutex()
    {
        return _mutex;
    }
    //获取条件变量
    pthread_cond_t &GetCond()
    {
        return _cond;
    }
    void ThreadWait()
    {
        int n = pthread_cond_wait(&_cond, &_mutex);
        assert(0 == n);
        (void)n;
    }

public:

    //获取线程池单例
    static ThreadPool<T>* GetInstance()
    {
        if(_ins == nullptr)
        {
            std::lock_guard<std::mutex> lg(_lock);
            if(nullptr == _ins)
            {
                _ins = new ThreadPool<T>();
            }
        }
        return const_cast<ThreadPool<T>*>(_ins);
    }
    //发布任务
    void push(const T &t)
    {
        LockGuard lg(_mutex);
        _taskQueue.push(t);
        pthread_cond_signal(&_cond);
    }
    //多线程启动
    void run()
    {
        for (auto &e : _threads)
        {
            ThreadPoolData<T> *tpd = new ThreadPoolData<T>(this, e->thread_name());
            e->start(handlerTask, tpd);
            std::cout << e->thread_name() << " start ... " << std::endl;
        }
    }
    
    static void delInstance()
    {
        LockGuard lg(_lock);
        if(_ins)
            delete _ins;
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (auto &e : _threads)
        {
            e->join();
            delete e;
        }
    }

private:
    std::queue<T> _taskQueue;
    int _threadNum;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    std::vector<Thread *> _threads;

    static volatile ThreadPool<T>* _ins;
    static std::mutex _lock;
    static GC _gc; //垃圾回收期，设置成静态，进程结束后自动调用进程池析构
};

template<class T>
volatile ThreadPool<T>* ThreadPool<T>::_ins = nullptr;

template<class T>
std::mutex  ThreadPool<T>::_lock;

template<class T>
typename ThreadPool<T>::GC ThreadPool<T>::_gc;